"""
工具管理器

这个模块负责管理和集成各种外部工具，包括：
- 搜索引擎工具
- 文档处理工具
- API调用工具
- 计算工具等
- RAG工具（检索增强生成）
"""

import logging
import os
import json
import requests
from typing import List, Dict, Any, Optional, Callable
from datetime import datetime

from langchain.tools import Tool
from langchain_community.tools import DuckDuckGoSearchRun
from langchain_community.utilities import SerpAPIWrapper

from config.settings import settings

logger = logging.getLogger(__name__)

class ToolManager:
    """
    工具管理器类
    
    负责管理和提供各种工具的访问接口。
    支持动态加载和配置工具。
    """
    
    def __init__(self):
        """初始化工具管理器"""
        self.tools: Dict[str, Tool] = {}
        self.available_tools: List[str] = []
        self._initialize_tools()
    
    def _initialize_tools(self):
        """初始化所有可用工具"""
        logger.info("正在初始化工具管理器...")
        
        try:
            # 初始化搜索工具
            self._initialize_search_tools()
            
            # 初始化计算工具
            self._initialize_calculation_tools()
            
            # 初始化文档工具
            self._initialize_document_tools()
            
            # 初始化时间工具
            self._initialize_time_tools()
            
            # 初始化系统工具
            self._initialize_system_tools()
            
            # 初始化RAG工具
            self._initialize_rag_tools()
            
            self.available_tools = list(self.tools.keys())
            logger.info(f"工具管理器初始化完成，已加载 {len(self.tools)} 个工具")
            
        except Exception as e:
            logger.error(f"工具管理器初始化失败: {str(e)}")
    
    def _initialize_search_tools(self):
        """初始化搜索工具"""
        try:
            # DuckDuckGo搜索工具
            ddg_search = DuckDuckGoSearchRun()
            self.tools["duckduckgo_search"] = Tool(
                name="DuckDuckGo搜索",
                description="使用DuckDuckGo搜索引擎搜索最新信息。输入应该是搜索查询字符串。",
                func=ddg_search.run
            )
            logger.info("已加载DuckDuckGo搜索工具")
            
            # SerpAPI搜索工具（如果有API密钥）
            if settings.SERPAPI_API_KEY:
                serpapi = SerpAPIWrapper(serpapi_api_key=settings.SERPAPI_API_KEY)
                self.tools["serpapi_search"] = Tool(
                    name="Google搜索",
                    description="使用Google搜索引擎搜索最新信息。输入应该是搜索查询字符串。",
                    func=serpapi.run
                )
                logger.info("已加载SerpAPI搜索工具")
            
        except Exception as e:
            logger.error(f"初始化搜索工具失败: {str(e)}")
    
    def _initialize_calculation_tools(self):
        """初始化计算工具"""
        try:
            # 基础计算器
            def calculator(expression: str) -> str:
                """安全的数学表达式计算器"""
                try:
                    # 只允许安全的数学运算
                    allowed_chars = set('0123456789+-*/.() ')
                    if not all(c in allowed_chars for c in expression):
                        return "错误：表达式包含不允许的字符"
                    
                    # 使用eval进行计算（在受控环境中）
                    result = eval(expression, {"__builtins__": {}}, {})
                    return f"计算结果: {result}"
                    
                except Exception as e:
                    return f"计算错误: {str(e)}"
            
            self.tools["calculator"] = Tool(
                name="计算器",
                description="执行基础数学计算。输入应该是数学表达式，如 '2+2' 或 '10*5'。",
                func=calculator
            )
            logger.info("已加载计算器工具")
            
        except Exception as e:
            logger.error(f"初始化计算工具失败: {str(e)}")
    
    def _initialize_document_tools(self):
        """初始化文档处理工具"""
        try:
            # 文档摘要工具
            def document_summary(text: str) -> str:
                """生成文档摘要"""
                try:
                    # 简单的摘要逻辑（可以后续集成更复杂的摘要模型）
                    sentences = text.split('。')
                    if len(sentences) <= 3:
                        return text
                    
                    # 取前3句作为摘要
                    summary = '。'.join(sentences[:3]) + '。'
                    return f"文档摘要: {summary}"
                    
                except Exception as e:
                    return f"摘要生成错误: {str(e)}"
            
            self.tools["document_summary"] = Tool(
                name="文档摘要",
                description="为长文档生成摘要。输入应该是需要摘要的文本内容。",
                func=document_summary
            )
            logger.info("已加载文档摘要工具")
            
        except Exception as e:
            logger.error(f"初始化文档工具失败: {str(e)}")
    
    def _initialize_time_tools(self):
        """初始化时间相关工具"""
        try:
            # 当前时间工具
            def get_current_time(format_type: str = "default") -> str:
                """获取当前时间"""
                try:
                    now = datetime.now()
                    
                    if format_type == "date":
                        return now.strftime("%Y-%m-%d")
                    elif format_type == "time":
                        return now.strftime("%H:%M:%S")
                    elif format_type == "full":
                        return now.strftime("%Y-%m-%d %H:%M:%S")
                    else:
                        return now.strftime("%Y年%m月%d日 %H:%M:%S")
                        
                except Exception as e:
                    return f"获取时间错误: {str(e)}"
            
            self.tools["current_time"] = Tool(
                name="当前时间",
                description="获取当前日期和时间。可选参数：'date'(仅日期)、'time'(仅时间)、'full'(完整格式)。",
                func=get_current_time
            )
            logger.info("已加载时间工具")
            
        except Exception as e:
            logger.error(f"初始化时间工具失败: {str(e)}")
    
    def _initialize_system_tools(self):
        """初始化系统工具"""
        try:
            # 天气查询工具（示例）
            def get_weather(city: str) -> str:
                """获取天气信息（示例实现）"""
                try:
                    # 这里可以集成真实的天气API
                    return f"抱歉，天气查询功能暂未实现。您查询的城市是：{city}"
                    
                except Exception as e:
                    return f"天气查询错误: {str(e)}"
            
            self.tools["weather"] = Tool(
                name="天气查询",
                description="查询指定城市的天气信息。输入应该是城市名称。",
                func=get_weather
            )
            logger.info("已加载天气查询工具")
            
        except Exception as e:
            logger.error(f"初始化系统工具失败: {str(e)}")

    def _initialize_rag_tools(self):
        """初始化RAG工具"""
        try:
            # 导入RAG工具
            from tools.rag_tools import get_rag_tools
            
            # 获取所有RAG工具
            rag_tools = get_rag_tools()
            
            # 将RAG工具添加到工具管理器中
            for tool in rag_tools:
                self.tools[tool.name] = tool
            
            logger.info(f"已加载 {len(rag_tools)} 个RAG工具")
            
        except ImportError as e:
            logger.warning(f"无法导入RAG工具，可能是依赖缺失: {str(e)}")
        except Exception as e:
            logger.error(f"初始化RAG工具失败: {str(e)}")

    def get_tool(self, tool_name: str) -> Optional[Tool]:
        """
        获取指定工具
        
        Args:
            tool_name (str): 工具名称
            
        Returns:
            Optional[Tool]: 工具对象，如果不存在则返回None
        """
        return self.tools.get(tool_name)
    
    def get_all_tools(self) -> List[Tool]:
        """
        获取所有可用工具
        
        Returns:
            List[Tool]: 工具列表
        """
        return list(self.tools.values())
    
    def get_tool_names(self) -> List[str]:
        """
        获取所有工具名称
        
        Returns:
            List[str]: 工具名称列表
        """
        return self.available_tools.copy()
    
    def add_custom_tool(self, name: str, description: str, func: Callable) -> bool:
        """
        添加自定义工具
        
        Args:
            name (str): 工具名称
            description (str): 工具描述
            func (Callable): 工具函数
            
        Returns:
            bool: 是否添加成功
        """
        try:
            tool = Tool(
                name=name,
                description=description,
                func=func
            )
            
            self.tools[name] = tool
            if name not in self.available_tools:
                self.available_tools.append(name)
            
            logger.info(f"已添加自定义工具: {name}")
            return True
            
        except Exception as e:
            logger.error(f"添加自定义工具失败: {str(e)}")
            return False
    
    def remove_tool(self, tool_name: str) -> bool:
        """
        移除工具
        
        Args:
            tool_name (str): 工具名称
            
        Returns:
            bool: 是否移除成功
        """
        try:
            if tool_name in self.tools:
                del self.tools[tool_name]
                if tool_name in self.available_tools:
                    self.available_tools.remove(tool_name)
                
                logger.info(f"已移除工具: {tool_name}")
                return True
            else:
                logger.warning(f"工具不存在: {tool_name}")
                return False
                
        except Exception as e:
            logger.error(f"移除工具失败: {str(e)}")
            return False
    
    def execute_tool(self, tool_name: str, input_data: str) -> str:
        """
        执行指定工具
        
        Args:
            tool_name (str): 工具名称
            input_data (str): 输入数据
            
        Returns:
            str: 执行结果
        """
        try:
            tool = self.get_tool(tool_name)
            if not tool:
                return f"错误：工具 '{tool_name}' 不存在"
            
            result = tool.run(input_data)
            logger.debug(f"工具 {tool_name} 执行完成")
            return result
            
        except Exception as e:
            error_msg = f"工具执行错误: {str(e)}"
            logger.error(error_msg)
            return error_msg
    
    def get_tool_info(self) -> Dict[str, Any]:
        """
        获取工具管理器信息
        
        Returns:
            Dict[str, Any]: 工具信息
        """
        return {
            "total_tools": len(self.tools),
            "available_tools": self.available_tools,
            "tool_descriptions": {
                name: tool.description 
                for name, tool in self.tools.items()
            }
        }
    
    def is_tool_available(self, tool_name: str) -> bool:
        """
        检查工具是否可用
        
        Args:
            tool_name (str): 工具名称
            
        Returns:
            bool: 是否可用
        """
        return tool_name in self.tools

# 创建全局工具管理器实例
tool_manager = ToolManager() 